export class Player extends Ac_Game_Object {
   constructor(playground, x, y, radius, color, speed, character, username, photo) {
       super();
       this.playground = playground;
       this.ctx = this.playground.game_map.ctx;
       this.x = x;
       this.y = y;
       this.move_length = 0;
       this.speed = speed;
       this.vx = 0;
       this.vy = 0;
       this.radius = radius;
       this.color = color;
       this.character = character;
       this.username = username;
       this.photo = photo;
       this.esp = 0.01;
       this.cur_skill = null;
       this.damage_x = 0;
       this.damag_y = 0;
       this.damage_speed = 0;
       this.friction = 0.9;
       this.time_spend = 0;
       this.fireballs = []; // 将发射的子弹都存下来
       if(this.character !== "robot") {
            this.img = new Image();
            this.img.src = this.photo;
       }

       if(this.character === "me") {
            this.fireball_coldtime = 3;
            this.fireball_img = new Image();
            this.fireball_img.src = "https://cdn.acwing.com/media/article/image/2021/12/02/1_9340c86053-fireball.png";

            this.blink_coldtime = 5;
            this.blink_img = new Image();
            this.blink_img.src = "https://cdn.acwing.com/media/article/image/2021/12/02/1_daccabdc53-blink.png";
       }
   }

   start() {
       this.playground.player_count ++;
       this.playground.notice_board.write("已就绪" + this.playground.player_count + "人");

       if(this.playground.player_count >= 3) {
           this.playground.state = "Fighting";
           this.playground.notice_board.write("Fighting")
       }
       if (this.character === "me") {
           this.add_listening_event();
       } else if (this.character === "robot"){
           let tx = Math.random() * this.playground.width / this.playground.scale;
           let ty = Math.random() * this.playground.height / this.playground.scale;
           this.move_to(tx, ty);
       }
   }

   add_listening_event() {
       let outer = this;
       this.playground.game_map.$canvas.on("contextmenu", function(){
           return false;
       });
       this.playground.game_map.$canvas.on("mousedown", function(e){
           if (outer.playground.state !== "Fighting")
               return true;

           const rect = outer.ctx.canvas.getBoundingClientRect();
           if(e.which === 3) {
                 let tx = (e.clientX - rect.left) / outer.playground.scale;
                 let ty = (e.clientY - rect.top) / outer.playground.scale;
                 outer.move_to(tx, ty);
                 if (outer.playground.mode === "multi mode") {
                    outer.playground.mps.send_move_to(tx, ty);
                 }
           }else if(e.which === 1) {
                 let tx = (e.clientX -rect.left) / outer.playground.scale;
                 let ty = (e.clientY - rect.top) / outer.playground.scale;
                 if (outer.cur_skill === "fire_ball") {
                      if (outer.fireball_coldtime > outer.esp)
                          return false;
                      let fireball = outer.short_fireball(tx, ty);
                      if (outer.playground.mode === "multi mode") {
                         outer.playground.mps.send_shoot_fireball(tx, ty, fireball.uuid);
                      }
                 } else if(outer.cur_skill === "blink") {
                        if (outer.blink_coldtime > outer.esp)
                            return false;
                        outer.blink(tx, ty);
                        if (outer.playground.mode === "multi mode") {
                            outer.playground.mps.send_blink(tx, ty);
                        }
                 }
                 outer.cur_skill = null;
           }
       });

       this.playground.game_map.$canvas.keydown(function(e){
           if (e.which === 13) {
                if (outer.playground.mode === "multi mode") {
                    outer.playground.chat_field.show_input();
                    return false;
                }} else if (e.which === 27) {
                    if (outer.playground.mode === "multi mode") {
                        outer.playground.chat_field.hide_input();
                    }
                }
           
           if (outer.playground.state !== "Fighting")
                return true;

           if (e.which === 81) {
                if (outer.fireball_coldtime > outer.esp)
                    return true;

                outer.cur_skill = "fire_ball";
                return false;
           } else if (e.which === 70) {
                if (outer.blink_coldtime > outer.esp)
                    return true;

                outer.cur_skill = "blink";
                return false;
           }
       });
   }
   
   short_fireball(tx, ty) {
      let x = this.x;
      let y = this.y;
      let radius = 0.01;
      let color = "orange";
      let angle = Math.atan2(ty - this.y, tx - this.x);
      let vx = Math.cos(angle);
      let vy = Math.sin(angle);
      let speed = 0.5;
      let move_length = 1;
      let fireball = new Fire_Ball(this.playground, this, vx, vy ,x, y, radius, color, speed, move_length, 0.01);
      this.fireballs.push(fireball);
      this.fireball_coldtime = 0.01;
      return fireball; // 将发射的子弹都存下来
   }

   destroy_fireball(uuid) {
      for (let i = 0; i < this.fireballs.length; i ++) {
         let fireball = this.fireballs[i];
         if (fireball.uuid === uuid) {
            fireball.destroy();
            break;
         }
      }
   }

   blink(tx, ty) {
        let d = this.get_dist(this.x, this.y, tx, ty);
        d = Math.min(d, 0.8);
        let angle = Math.atan2(ty - this.y, tx - this.x);
        this.x += d * Math.cos(angle);
        this.y += d * Math.sin(angle);
        this.blink_coldtime = 5;
        this.move_length = 0; // 闪现完停下来
   }

   get_dist (x1, y1, x2, y2) {
      let dx = x1 - x2;
      let dy = y1 - y2;
      return Math.sqrt(dx * dx + dy * dy);
   }

   move_to (tx, ty) {
       this.move_length = this.get_dist(this.x, this.y, tx, ty);
       let angle = Math.atan2(ty - this.y, tx - this.x);
       this.vx = Math.cos(angle);
       this.vy = Math.sin(angle);
   }

   is_attacked(angle, damage) {
       for (let i = 0; i < 20 + Math.random() * 5; i ++) {
              let x = this.x;
              let y = this.y;
              let angle = Math.PI * 2 * Math.random();
              let vx = Math.cos(angle);
              let vy = Math.sin(angle);
              let speed = this.speed * 10;
              let radius = this.radius * Math.random() * 0.1;
              let color = this.color;
              let move_length = this.radius * Math.random() * 5;
              new Particle(this.playground, x, y, vx, vy, radius, color, speed, move_length);
       }
       this.radius -= damage;
       if (this.radius < this.esp) {
            this.destroy();
            return false;
       }
       this.damage_x = Math.cos(angle);
       this.damage_y = Math.sin(angle);
       this.damage_speed = damage * 100;
       this.speed * 0.8;
    }

    receive_attack(x, y, angle, damage, ball_uuid, attacker) {
        attacker.destroy_fireball(ball_uuid); // 击中敌人后让敌人窗口的炮弹消失
        this.x = x; // 同步自己被攻击后的坐标
        this.y = y;
        this.is_attacked(angle, damage); // 调用自己被攻击的函数
    }

    update() {
        this.update_win();
        this.time_spend += this.timedelta / 1000;
        if (this.character === "me" && this.playground.state === "Fighting") {
            this.update_coldtime();
        }
        this.update_move();
        this.render();
    }

    update_win() {
        if (this.playground.state === "Fighting" && this.character === "me" && this.playground.players.length === 1) {
           this.playground.state = "over";
           this.playground.score_board.win();
        }
    }

    update_coldtime() {
        this.fireball_coldtime -= this.timedelta / 1000;
        this.fireball_coldtime = Math.max(this.fireball_coldtime, 0);
        this.blink_coldtime -= this.timedelta / 1000;
        this.blink_coldtime = Math.max(this.blink_coldtime, 0);
    }

    update_move() {
        if (Math.random() < 1 / 240 && this.time_spend > 5 && this.character === "robot") {
            let player = this.playground.players[Math.floor(Math.random() * this.playground.players.length)];
            let tx = player.x + player.speed + this.vx + this.timedelta / 1000 * 0.3;
            let ty = player.y + player.speed + this.vy + this.timedelta / 1000 * 0.3;
            this.short_fireball(tx, ty);
        }
        if (this.damage_speed > this.esp){
            this.vx = this.vy = 0;
            this.move_length = 0;
            this.x += this.damage_x * this.damage_speed * this.timedelta / 1000;
            this.y += this.damage_y * this.damage_speed * this.timedelta / 1000;
            this.damage_speed *= this.friction;
        }
        else {
            if(this.move_length < this.esp) {
                this.move_length = 0;
                this.vx = 0;
                this.vy = 0;
                if(this.character === "robot") {
                    let tx = Math.random() * this.playground.width / this.playground.scale;
                    let ty = Math.random() * this.playground.height / this.playground.scale;
                    this.move_to(tx, ty);
                }
             } else {
                let moved = Math.min(this.move_length, this.speed * this.timedelta / 1000);
                this.x += this.vx * moved;
                this.y += this.vy * moved;
                this.move_length -= moved;
             }
        }
    }

    render() {
        let scale = this.playground.scale;
        if(this.character !== "robot") {
            this.ctx.save();
            this.ctx.beginPath();
            this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, Math.PI * 2, false);
            this.ctx.stroke();
            this.ctx.clip();
            this.ctx.drawImage(this.img, (this.x - this.radius) * scale, (this.y - this.radius) * scale, this.radius * 2 * scale, this.radius * 2 * scale); 
            this.ctx.restore();
        }
        else {
            this.ctx.beginPath();
            this.ctx.arc(this.x * scale, this.y * scale, this.radius * scale, 0, 2*Math.PI, false );
            this.ctx.fillStyle = this.color;
            this.ctx.fill();
        }

        if (this.character === "me" && this.playground.state === "Fighting") {
            this.render_skill_coldtime();
        }
    }

    render_skill_coldtime() {
        let scale = this.playground.scale;
        let x = 1.5, y = 0.9, r = 0.04;
        this.ctx.save();
        this.ctx.beginPath();
        this.ctx.arc(x * scale, y * scale, r * scale, 0, Math.PI * 2, false);
        this.ctx.stroke();
        this.ctx.clip();
        this.ctx.drawImage(this.fireball_img, (x - r) * scale, (y - r) * scale, r * 2 * scale, r * 2 * scale); 
        this.ctx.restore();
        if (this.fireball_coldtime > 0){
            this.ctx.beginPath();
            this.ctx.moveTo(x * scale, y * scale);
            this.ctx.arc(x * scale, y * scale, r * scale, 0 - Math.PI / 2, 2 * Math.PI *(1 - this.fireball_coldtime / 3) - Math.PI / 2, true);
            this.ctx.lineTo(x * scale, y * scale);
            this.ctx.fillStyle = "rgba(0, 0, 255, 0.6)";
            this.ctx.fill();
        }
        x = 1.62, y = 0.9, r = 0.04;
        this.ctx.save();
        this.ctx.beginPath();
        this.ctx.arc(x * scale, y * scale, r * scale, 0, Math.PI * 2, false);
        this.ctx.stroke();
        this.ctx.clip();
        this.ctx.drawImage(this.fireball_img, (x - r) * scale, (y - r) * scale, r * 2 * scale, r * 2 * scale); 
        this.ctx.restore();
        if (this.blink_coldtime > 0){
            this.ctx.beginPath();
            this.ctx.moveTo(x * scale, y * scale);
            this.ctx.arc(x * scale, y * scale, r * scale, 0 - Math.PI / 2, 2 * Math.PI *(1 - this.blink_coldtime / 5) - Math.PI / 2, true);
            this.ctx.lineTo(x * scale, y * scale);
            this.ctx.fillStyle = "rgba(0, 0, 255, 0.6)";
            this.ctx.fill();
        }
    }

    on_destroy() {
        if (this.character === "me") {
            if (this.playground.state === "Fighting") {
                this.playground.state = "over";
                this.playground.score_board.lose();
            }
        }
        for (let i = 0; i < this.playground.players.length; i ++) {
            if (this.playground.players[i] === this) {
                this.playground.players.splice(i, 1);
                break;
            }
        }
    }
}

